'use strict';

const ERR_CODE = require('../constants/errorCode');
const moment = require('moment');

// 数据库表名
const MYSQL_TABLE = 'email_verify_code';

// 获取Service类
const Service = require('egg').Service;

class EmailService extends Service {
  async sendVerifyCode(email) {
    const { ctx, app } = this;
    try {
    // 查询数据库 email_verify_code 表中是否有这个邮箱
      let result1 = await app.mysql.get(MYSQL_TABLE, { email });

      // 如果表里没有这个邮箱，则新建一条数据
      if (!result1) {
        result1 = await app.mysql.insert(MYSQL_TABLE, {
          email,
          verify_code: null,
          update_time: app.mysql.literals.now,
          create_time: app.mysql.literals.now,
        });
      }

      // 生成验证码
      const verifyCode = ctx.helper.getVerifyCode();

      // 发送验证码
      const success = await ctx.service.nodemailer.sendMail(email, verifyCode);
      if (!success) throw (ERR_CODE.Email_SendFail);

      // 更新 email_verify_code表中的记录
      const row = {
        verify_code: verifyCode,
        update_time: app.mysql.literals.now,
      };

      const options = {
        where: {
          email_id: result1.email_id,
        },
      };
      const result2 = await app.mysql.update(MYSQL_TABLE, row, options);
      if (result2.affectedRows !== 1) throw (ERR_CODE.Email_DBUpdateFail);

      return true;
    } catch (err) {
      switch (err) {
        case ERR_CODE.Email_SendFail:
          ctx.throw(422, '验证码发送失败', {
            errCode: ERR_CODE.Email_SendFail,
            description: 'nodemailer服务错误，验证码发送失败',
          });
          break;
        case ERR_CODE.Email_DBUpdateFail:
          ctx.throw(422, '验证码无效', {
            errCode: ERR_CODE.Email_DBUpdateFail,
            description: '数据库出错，验证码无效',
          });
          break;
        default:
          throw (err);
      }
    }
  }

  async checkVerifyCode(email, verifyCode) {
    const { ctx, app } = this;

    try {
    // 获取 email 表中的verifyCode
      const result = await app.mysql.select(MYSQL_TABLE, {
        where: { email }, // WHERE 条件
        columns: [ 'verify_code', 'update_time' ], // 要查询的表字段
        orders: [[ 'email_id', 'asc' ]], // 排序方式
        limit: 1, // 返回数据量
        offset: 0, // 数据偏移量
      });

      if (result.length === 0) throw (ERR_CODE.Email_NoMailInfo);

      // 验证码是否过期，过期时间为30min
      const isExpired = moment(new Date()).diff(moment(result[0].update_time), 'minute') > 30;

      if (isExpired) { throw (ERR_CODE.Email_Expired); }


      // 验证码是否正确
      const isCodeValid = verifyCode === result[0].verify_code;

      if (!isCodeValid) throw (ERR_CODE.Email_VerificationFail);

      return true;
    } catch (err) {
      switch (err) {
        case ERR_CODE.Email_NoMailInfo:
          ctx.throw(422, '验证码校验失败，系统无此邮箱信息', {
            errCode: ERR_CODE.Email_NoMailInfo,
            description: '验证码校验失败，系统无此邮箱信息',
          });
          break;
        case ERR_CODE.Email_Expired:
          ctx.throw(422, '验证码已经失效，请重新获取验证码', {
            errCode: ERR_CODE.Email_Expired,
            description: '验证码已失效',
          });
          break;
        case ERR_CODE.Email_VerificationFail:
          ctx.throw(422, '验证码错误，请填写正确的验证码', {
            errCode: ERR_CODE.Email_VerificationFail,
            description: '验证码错误',
          });
          break;
        default:
          throw (err);
      }
    }
  }
}

module.exports = EmailService;
